﻿using DisplayReading;
using DisplayReading.Model;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.Integration;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using Emgu.CV;
using Emgu.CV.CvEnum;
using System.Security.Cryptography;
using Emgu.CV.Structure;
using System.Net;
using System.Text.RegularExpressions;
using System.Windows.Media.Media3D;
using System.Net.Sockets;
using System.Windows;
using BaseDll;
using Emgu.CV.Ocl;

namespace DisplayReadingWinform
{
    public partial class WpfForm : Form
    {
        ElementHost host { get; set; }
        /// <summary>
        /// 
        /// </summary>
        ucDispaly uc { get; set; }

        /// <summary>
        /// 显示器
        /// </summary>
        Screen[] screens { get; set; }

        Task SendTask { get; set; }

        bool taskRunFlag { get; set; } = true;
        const int WIDTH = 1920;  // 设置读取的图片宽度
        const int HEIGHT = 1080; // 设置读取的图片高度
        const int NUM_SLICE = 24; // 切片数量

        /// <summary>
        /// 服务
        /// </summary>
        public List<UdpClient> server { get; set; }
        public WpfForm()
        {
            InitializeComponent();
            host = new ElementHost();
            this.FormClosing += WpfForm_FormClosing;
            CvInvoke.UseOpenCL = true;
        }

        private void WpfForm_FormClosing(object? sender, FormClosingEventArgs e)
        {
            taskRunFlag = false;
            uc.data.Clear();
        }

        private void WpfForm_Load(object sender, EventArgs e)
        {
            uc = new ucDispaly();
            host.Child = uc;
            this.Controls.Add(host);
            host.Dock = DockStyle.Fill;
            uc.data.ServerStart(NUM_SLICE);
            server = uc.data.sendServer.server;
            GetScreen();
            SendTask = Task.Factory.StartNew(SendFun);
        }

        private void SetText(string str)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action<string>(SetText), str);
            }
            else
            {
                this.Text = str;
            }
        }

        private void SendFun()
        {
            DateTime startDT = System.DateTime.Now;
            Mat[] img = new Mat[NUM_SLICE];
            while (taskRunFlag)
            {
                var display = uc.data.displayList.Find(x => x.ischeck);
                if (display != null)
                {
                    try
                    {
                        screenshot = GetScreenBitmap(display);
                    }
                    catch
                    {
                        Thread.Sleep(1000);
                        continue;
                    }
                    if (screenshot != null)
                    {
                        // 计算两次循环间的间隔，并显示在左上角
                        DateTime stopDT = System.DateTime.Now;
                        TimeSpan ts = stopDT.Subtract(startDT);
                        SetText("图片处理耗时：" + ts.TotalMilliseconds + "ms");
                        
                        startDT = System.DateTime.Now;

                        // 读取一张图片
                        Mat currentImage = screenshot.ToMat();
                        if (uc.data.preview)
                        {
                            var senddata = BitmapToImageSource(screenshot);
                            uc.SetPreview(senddata.Item1);
                        }
                        int N = currentImage.Rows / NUM_SLICE;
                        for (Int32 i = 0; i < NUM_SLICE; i++)
                        {
                            if (i== NUM_SLICE-1)
                            {
                                // 从原图中切割，输入参数：原始图片 行范围row 列范围col
                                img[i] = new Mat(currentImage, new Emgu.CV.Structure.Range(i * N, currentImage.Rows), new Emgu.CV.Structure.Range(0, currentImage.Cols));
                            }
                            else
                            {
                                // 从原图中切割，输入参数：原始图片 行范围row 列范围col
                                img[i] = new Mat(currentImage, new Emgu.CV.Structure.Range(i * N, (i + 1) * N - 1), new Emgu.CV.Structure.Range(0, currentImage.Cols));
                            }
                         
                        }
                        // 将切片压缩后发送到接收端                
                        Parallel.For(0, NUM_SLICE, i => // Parallel并进加速
                                                        //for(int i = 0; i < NUM_SLICE; i++) // 普通串行方法
                        {
                            // 从原图中切割，输入参数：原始图片 行范围row 列范围col
                            //img[i] = new Mat(currentImage, new Emgu.CV.Structure.Range(i * N, (i + 1) * N - 1), new Emgu.CV.Structure.Range(0, WIDTH));
                            // 显示
                            //imgbox[i].Image = img[i];
                           // CvInvoke.PutText(img[i], "size"+i,new System.Drawing.Point(1,1),FontFace.HersheyComplexSmall, 5,new MCvScalar(255,0,0));
                            // 转换格式
                            Image<Bgr, Byte> img_trans = img[i].ToImage<Bgr, Byte>();
                            // JPEG压缩
                            byte[] bytes = img_trans.ToJpegData(95);
                            IPEndPoint sendPort = new IPEndPoint(IPAddress.Parse("127.0.0.1"),  i+ uc.data.config._sendPort+1);
                            server[i].Send(bytes, bytes.Length, sendPort);


                            //// 添加时间戳
                            ////byte[] sec = { (byte)((((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000) & 0xFF00) >> 8),
                            ////            (byte)(((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000) & 0xFF)};
                            ////bytes.Concat(sec);
                        }
                        );
                    }
                    GC.Collect();

                }
                int sleep = 50;
                if (uc.data.fps > 0)
                {
                    sleep = 1000 / uc.data.fps;
                    if (sleep < 20)
                    {
                        sleep = 20;
                    }
                }
                Thread.Sleep(sleep);
            }
        }
        public Tuple<BitmapImage, byte[]> BitmapToImageSource(Bitmap bitmap)
        {
            using (MemoryStream memoryStream = new MemoryStream())
            {
                // Save the bitmap to the memory stream
                bitmap.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png);
                memoryStream.Position = 0;

                // Create a BitmapImage and initialize it with the memory stream
                BitmapImage bitmapImage = new BitmapImage();
                bitmapImage.BeginInit();
                bitmapImage.StreamSource = memoryStream;
                bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
                bitmapImage.EndInit();

                // Freeze the BitmapImage for better performance
                bitmapImage.Freeze();
                byte[] bytes = new byte[memoryStream.Length];
                memoryStream.Read(bytes, 0, bytes.Length);

                return Tuple.Create(bitmapImage, bytes);
            }
        }

        public byte[] BitmapToByte(System.Drawing.Bitmap bitmap)
        {
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
            ms.Seek(0, System.IO.SeekOrigin.Begin);
            byte[] bytes = new byte[ms.Length];
            ms.Read(bytes, 0, bytes.Length);
            ms.Dispose();
            return bytes;
        }
        private void GetScreen()
        {
            screens = Screen.AllScreens;
            List<DisplayData> diss = new List<DisplayData>();
            foreach (var screen in screens)
            {
                diss.Add(new DisplayData()
                {
                    name = screen.DeviceName,
                });
            }
            uc.data.displayList = diss;
        }
        Bitmap screenshot;
        /// <summary>
        /// 获取显示器截图
        /// </summary>
        /// <returns></returns>
        private Bitmap GetScreenBitmap(DisplayData display)
        {
            Screen screen = null;
            foreach (var item in screens)
            {
                if (item.DeviceName == display.name)
                {
                    screen = item;
                }
            }
            if (screen == null && screens.Length > 0)
            {
                screen = screens[0];
            }
            // 创建与当前显示器大小相匹配的位图
            screenshot = new Bitmap(screen.Bounds.Width, screen.Bounds.Height);
            // 绘制鼠标光标的位置
            System.Drawing.Point mousePosition = System.Windows.Forms.Cursor.Position;
            System.Drawing.Point relativeMousePosition = new System.Drawing.Point(mousePosition.X - screen.Bounds.X, mousePosition.Y - screen.Bounds.Y);
            using (Graphics g = Graphics.FromImage(screenshot))
            {
                g.CopyFromScreen(screen.Bounds.Location, System.Drawing.Point.Empty, screen.Bounds.Size);
                g.DrawEllipse(new System.Drawing.Pen(new SolidBrush(System.Drawing.Color.Red), 3), (float)relativeMousePosition.X - 5, (float)relativeMousePosition.Y - 5, 10, 10);
            }
            return screenshot;
            //// 显示截图或进行其他处理
            //// 例如可以将截图显示在不同的 Image 控件中


            //// 创建一个新的 Image 控件来显示截图
            //System.Windows.Controls.Image imageView = new System.Windows.Controls.Image();
            //imageView.Source = imageSource;

            //// 添加到 WPF 窗口中
            //stackPanel.Children.Add(imageView);
        }
    }
}
